﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Citi.Scheduler.Domain;
using Citi.Scheduler.WebUi.Models;
using Webdiyer.WebControls.Mvc;
using Citi.Helpers;

namespace Citi.Scheduler.WebUi.Controllers
{
    public class LibraryVersionController : ControllerBase<LibraryVersionModel, LibraryVersion>
    {
        public ActionResult Upload(int id)
        {
            return PartialView(new LibraryVersionModel { Id = id });
        }

        [HttpPost]
        public ActionResult Upload(LibraryVersionModel model, IEnumerable<HttpPostedFileBase> files)
        {
            var version = new LibraryVersion().SelectById<LibraryVersion>(model.Id);
            string pathToSave = SaveDll(files, version);

            var fileDll = files.First();
            version.LibraryFile = Path.GetFileName(fileDll.FileName);

            try
            {
                System.Reflection.Assembly dll = System.Reflection.Assembly.LoadFile(pathToSave);
                version.Status = dll.GetExportedTypes().Any(x => RoutineBaseTypes.Any(y => y.IsAssignableFrom(x)))
                                     ? (int)Enums.LibraryStatus.Ok
                                     : (int)Enums.LibraryStatus.InvalidDll;
            }
            catch (Exception e)
            {
                version.Status = (int) Enums.LibraryStatus.Error;
                version.ChangeDescription += e.Message;
            }

            version.Save(version);

            if (version.Status == (int) Enums.LibraryStatus.Ok)
            {
                var routines = new Routine().GetRoutinesByLibraryIdAndTypeUsingLastVersion(version.LibraryId, version.Type).ToList();

                routines.ForEach(x =>
                    {
                        x.LibraryVersionId = version.Id;
                        x.Save(x);
                    });
            }

            return RedirectToAction("Form", "Library");
        }

        private string SaveDll(IEnumerable<HttpPostedFileBase> files, LibraryVersion version)
        {
            using (NetworkShareAccesser.Access(ServerName, NetworkUser, NetworkPassword))
            {
                var pathLibrary = Path.Combine(DllFolder, version.LibraryId.ToString(), ((LibraryType)version.Type).ToString());

                if (!Directory.Exists(pathLibrary))
                    Directory.CreateDirectory(pathLibrary);

                pathLibrary = Path.Combine(pathLibrary, version.Version);

                if (!Directory.Exists(pathLibrary))
                    Directory.CreateDirectory(pathLibrary);

                foreach (var file in files.Where(x => x != null))
                    file.SaveAs(Path.Combine(pathLibrary, Path.GetFileName(file.FileName)));

                return Path.Combine(pathLibrary, Path.GetFileName(files.First().FileName)); ;
            }
        }

        [OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
        public ActionResult Index(int libraryId, int page = 1)
        {
            var pagedList = GetPagedList(libraryId, page);

            return PartialView(pagedList);

            //return PartialView(new LibraryVersionModel().CreateModel(versions));
        }

        private PagedList<LibraryVersionModel> GetPagedList(int libraryId, int page)
        {
            var versions = new LibraryVersionModel().CreateModel(new LibraryVersion().GetByLibraryId(libraryId).OrderByDescending(x => x.Date));

            return new PagedList<LibraryVersionModel>(versions.ToList(), page, 3);
        }

        public ActionResult Create()
        {
            return CreateBase(true);
        }

        //[HttpPost]
        //public ActionResult Upload(HttpPostedFileWrapper dllFile)
        //{ 
        //    // Lógica para salvar a foto
        //    return View();
        //} 

        [HttpPost]
        public ActionResult Create(LibraryVersionModel model)
        {
            model.Date = DateTime.Now;
            model.LibraryFile = "There's no file";
            model.Status = Enums.LibraryStatus.NoFile;
            CreateBase(model);

            var pagedList = GetPagedList(model.LibraryId, 1);

            return PartialView("Index", pagedList);
        }

        private void DeleteDllFile(string dllPath)
        {
            using (NetworkShareAccesser.Access(ServerName, NetworkUser, NetworkPassword))
            {
                if (!string.IsNullOrEmpty(dllPath) && System.IO.File.Exists(Path.Combine(DllFolder, dllPath)))
                    System.IO.File.Delete(Path.Combine(DllFolder, dllPath));
            }
        }

        public ActionResult Delete(int id)
        {
            var library = new LibraryVersion().SelectById<LibraryVersion>(id);

            DeleteDllFile(Path.Combine(library.LibraryFile, ((LibraryType)library.Type).ToString()));

            return DeleteBase(id, true);
        }

        public ActionResult GetNextVersion(int libraryId, Enums.ChangeType changeType, LibraryType libraryType)
        {
            var libraryVersion = new LibraryVersion().GetLastByLibraryIdAndType(libraryId, (int)libraryType);

            if (libraryVersion == null)
                return Json(new { version = "1.0.0.0" });

            var version = libraryVersion.Version.Split('.');

            if (version.Count() != 4)
                return Json(new { version = "1.0.0.0" });

            switch (changeType)
            {
                case Enums.ChangeType.Build:
                    version[3] = (int.Parse(version[3]) + 1).ToString();
                    break;
                case Enums.ChangeType.Revision:
                    version[3] = "0";
                    version[2] = (int.Parse(version[2]) + 1).ToString();
                    break;
                case Enums.ChangeType.Minor:
                    version[3] = "0";
                    version[2] = "0";
                    version[1] = (int.Parse(version[1]) + 1).ToString();
                    break;
                case Enums.ChangeType.Major:
                    version[3] = "0";
                    version[2] = "0";
                    version[1] = "0";
                    version[0] = (int.Parse(version[0]) + 1).ToString();
                    break;
            }

            return Json(new { version = string.Join(".", version) });
        }

        public void FillViewBags(int? userId = null, int? libraryId = null)
        {
            var users = new User().SelectAllActive<User>().OrderBy(m => m.Name);
            ViewBag.Users = users.ToSelectList(x => x.Name, x => x.Id.ToString(), "Select an user",
                userId.HasValue ? userId.Value.ToString() : string.Empty);

            var libraries = new Library().SelectAllActive<Library>().OrderBy(m => m.Name);
            ViewBag.Libraries = libraries.ToSelectList(x => x.Name, x => x.Id.ToString(), "Select a library",
                libraryId.HasValue ? libraryId.Value.ToString() : string.Empty);

            ViewBag.Types = new LibraryType().ToSelectList(true, true, "Select a type");
            //ViewBag.Status = new Enums.LibraryStatus().ToSelectList(true, true, "Select a status");
            ViewBag.ChangeTypes = new Enums.ChangeType().ToSelectList(true, true, "Select a change type");
        }
    }
}
